#ifndef _H_C_PROTOCOL_SERVICE_ADAPTER_H_
#define _H_C_PROTOCOL_SERVICE_ADAPTER_H_

#include "../service.h"
#include "EProtocolErrorCode.h"
#include "ProtocolDelegate.h"
#include "SGetProtocolUserDataRet.h"
#include "SCallRpcRet.h"
#include "SProtocolPeerPoint.h"
#include "SProtocolServerPoint.h"
#include "SProtocolClientPoint.h"
#include "SProtocolSessionPoint.h"

namespace QWER
{
	QCLASS IProtocol;
	QCLASS IRpc;
	QCLASS IRpcData;
	QCLASS CProtocolMgr;
	QCLASS CToProtocolResolverMsgMgr;
	QCLASS CProtocolContainer;
	QCLASS CProtocolService;
    QCLASS CRpcCallbackInfo;
	QCLASS CProtocolHeader;

	QDLL_EXPORT QCLASS CProtocolServiceFrontend : public IServiceFrontend
	{
	public:
		CProtocolServiceFrontend(CService<CLogServiceFrontend>& roLogService, const SLogChannelUID& rsLogChannelUID);
#ifndef _USING_CLI
		~CProtocolServiceFrontend();
#endif
		inline PTR(IRunner) GetRunner() { return m_poHelper->GetRunner(); }
        inline PTR(CServiceFrontendHelper) GetHelper() { return m_poHelper; }

		CPromise<SProtocolPeer>& CreatePeer(const SProtocolAddress& rsAddress);
		CPromise<SProtocolServer>& CreateServer(const SProtocolAddress& rsServerAddress);
		CPromise<SProtocolClient>& CreateClient(const SProtocolAddress& rsServerAddress);

		void SetPeerMaxPackageSize(const SProtocolPeer& rsPeer, UINT32 dwMaxPackageSize);
		void SetServerMaxPackageSize(const SProtocolServer& rsPeer, UINT32 dwMaxPackageSize);
		void SetClientMaxPackageSize(const SProtocolClient& rsPeer, UINT32 dwMaxPackageSize);

		void RegisterRpcCall(const SProtocolPeerPoint& rsPeer, DOnRpcCall&& cbOnRpcCall);
		void SendRpc(const SProtocolPeerPoint& rsPeer, CONST_REF(SProtocolEndPoint) rsDstEndPoint, const std::shared_ptr<std::vector<UINT8>>& roRpcArg);
		void SendRpc(const SProtocolPeerPoint& rsPeer, QMOVEABLE(CProtocolHeader) poHeader, const std::shared_ptr<std::vector<UINT8>>& roRpcArg);
		CPromise<SRpcRet>& CallRpc(const SProtocolPeerPoint& rsPeer, CONST_REF(SProtocolEndPoint) rsEndPoint, const std::shared_ptr<std::vector<UINT8>>& roRpcArg, UINT32 dwTimeoutMilliSeconds);
		CPromise<SRpcRet>& CallRpc(const SProtocolPeerPoint& rsPeer, QMOVEABLE(CProtocolHeader) poHeader, const std::shared_ptr<std::vector<UINT8>>& roRpcArg, UINT32 dwTimeoutMilliSeconds);

		void RegisterRpcCall(const SProtocolServerPoint& rsServer, DOnRpcCall&& cbOnRpcCall);
		void SendRpc(const SProtocolSessionPoint& rsClientSessionID, const std::shared_ptr<std::vector<UINT8>>& roRpcArg);
		void SendRpc(const SProtocolSessionPoint& rsClientSessionID, QMOVEABLE(CProtocolHeader) poHeader, const std::shared_ptr<std::vector<UINT8>>& roRpcArg);
		CPromise<SRpcRet>& CallRpc(const SProtocolSessionPoint& rsClientSessionID, const std::shared_ptr<std::vector<UINT8>>& roRpcArg, UINT32 dwTimeoutMilliSeconds);
		CPromise<SRpcRet>& CallRpc(const SProtocolSessionPoint& rsClientSessionID, QMOVEABLE(CProtocolHeader) poHeader, const std::shared_ptr<std::vector<UINT8>>& roRpcArg, UINT32 dwTimeoutMilliSeconds);

		void RegisterRpcCall(const SProtocolClient& rsClient, DOnRpcCall&& cbOnRpcCall);
		void SendRpc(const SProtocolClientPoint& rsClient, const std::shared_ptr<std::vector<UINT8>>& roRpcArg);
		void SendRpc(const SProtocolClientPoint& rsClient, QMOVEABLE(CProtocolHeader) poHeader, const std::shared_ptr<std::vector<UINT8>>& roRpcArg);
		CPromise<SRpcRet>& CallRpc(const SProtocolClientPoint& rsClient, const std::shared_ptr<std::vector<UINT8>>& roRpcArg, UINT32 dwTimeoutMilliSeconds);
		CPromise<SRpcRet>& CallRpc(const SProtocolClientPoint& rsClient, QMOVEABLE(CProtocolHeader) poHeader, const std::shared_ptr<std::vector<UINT8>>& roRpcArg, UINT32 dwTimeoutMilliSeconds);

	protected:
		virtual void _Awake(PTR(CServiceFrontendHelper) roHelper) QOVERRIDE;

	private:
		void _SetMaxPackageSize(UINT64 qwProtocolEntityUID, UINT32 dwMaxPackageSize);
		void _RegisterRpcCall(UINT64 qwProtocolEntityUID, UINT16 wURI, DOnRpcCall&& cbOnRpcCall);
        void _SendRpc(UINT64 qwProtocolEntityUID, QMOVEABLE(CProtocolHeader) poHeader, const std::shared_ptr<std::vector<UINT8>>& roRpcArg, UINT32 dwTimeoutMilliSeconds, const SPromiseProcessor<SRpcRet>& rsRet);

	private:
		PTR(CServiceFrontendHelper) m_poHelper = NULL_PTR;
        CVector(PTR(CRpcCallbackInfo)) m_oRpcCallbackInfos;
		CService<CLogServiceFrontend>* m_poLogService = NULL_PTR;
		SLogChannelUID m_sLogChannelUID;
		CLogServiceFrontend* m_poLogServiceFrontend = NULL_PTR;
	};
}

#endif
